package com.nbcio.im.controller;

import com.nbcio.common.core.domain.R;
import com.nbcio.common.satoken.utils.LoginHelper;
import com.nbcio.common.websocket.holder.WebSocketSessionHolder;
import com.nbcio.im.service.ImService;
import com.nbcio.im.core.service.ImMessageService;
import com.nbcio.im.core.service.ImGroupService;
import com.nbcio.im.config.ImProperties;
import com.nbcio.system.domain.SysUser;
import com.nbcio.system.domain.vo.SysUserVo;
import com.nbcio.system.service.ISysUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * IM控制器
 *
 * @author nbacheng
 */
@Slf4j
@RestController
@RequestMapping("/im")
@RequiredArgsConstructor
@Tag(name = "即时通讯", description = "IM相关接口")
public class ImController {

    private final ImService imService;
    private final ISysUserService userService;
    private final ImMessageService imMessageService;
    private final ImGroupService imGroupService;
    private final ImProperties imProperties;

    @Operation(summary = "用户登录IM", description = "用户登录到IM系统")
    @PostMapping("/login")
    public R<Map<String, Object>> loginToIm() {
        try {
            Long userId = LoginHelper.getUserId();
            log.info("用户 {} 尝试登录IM系统", userId);
            
            SysUserVo userVo = userService.selectUserById(userId);
            if (userVo == null) {
                log.warn("用户 {} 不存在", userId);
                return R.fail("用户不存在");
            }
            
            log.info("用户 {} 当前IM状态: {}", userId, userVo.getImStatus());
            
            // 转换为SysUser
            SysUser user = new SysUser();
            user.setUserId(userVo.getUserId());
            user.setUserName(userVo.getUserName());
            user.setNickName(userVo.getNickName());
            user.setEmail(userVo.getEmail());
            user.setPhonenumber(userVo.getPhonenumber());
            user.setAvatar(userVo.getAvatar());
            user.setStatus(userVo.getStatus());
            
            R<Map<String, Object>> result = imService.loginToIm(user);
            log.info("用户 {} IM登录结果: {}", userId, result.getCode() == 200 ? "成功" : "失败");
            
            return result;
        } catch (Exception e) {
            log.error("用户登录IM失败: {}", e.getMessage(), e);
            return R.fail("登录IM失败: " + e.getMessage());
        }
    }

    @Operation(summary = "用户登出IM", description = "用户从IM系统登出")
    @PostMapping("/logout")
    public R<Void> logoutFromIm() {
        try {
            Long userId = LoginHelper.getUserId();
            return imService.logoutFromIm(userId);
        } catch (Exception e) {
            log.error("用户登出IM失败: {}", e.getMessage(), e);
            return R.fail("登出IM失败: " + e.getMessage());
        }
    }

    @Operation(summary = "同步用户到IM", description = "将系统用户同步到IM系统")
    @PostMapping("/sync-user")
    public R<Void> syncUserToIm(@RequestParam Long userId) {
        try {
            SysUserVo userVo = userService.selectUserById(userId);
            if (userVo == null) {
                return R.fail("用户不存在");
            }
            // 转换为SysUser
            SysUser user = new SysUser();
            user.setUserId(userVo.getUserId());
            user.setUserName(userVo.getUserName());
            user.setNickName(userVo.getNickName());
            user.setEmail(userVo.getEmail());
            user.setPhonenumber(userVo.getPhonenumber());
            user.setAvatar(userVo.getAvatar());
            user.setStatus(userVo.getStatus());
            return imService.syncUserToIm(user);
        } catch (Exception e) {
            log.error("同步用户到IM失败: {}", e.getMessage(), e);
            return R.fail("同步用户失败: " + e.getMessage());
        }
    }

    @Operation(summary = "批量同步用户到IM", description = "批量将系统用户同步到IM系统")
    @PostMapping("/batch-sync-users")
    public R<Void> batchSyncUsersToIm(@RequestBody List<Long> userIds) {
        try {
            List<SysUser> users = new ArrayList<>();
            for (Long userId : userIds) {
                SysUserVo userVo = userService.selectUserById(userId);
                if (userVo != null) {
                    SysUser user = new SysUser();
                    user.setUserId(userVo.getUserId());
                    user.setUserName(userVo.getUserName());
                    user.setNickName(userVo.getNickName());
                    user.setEmail(userVo.getEmail());
                    user.setPhonenumber(userVo.getPhonenumber());
                    user.setAvatar(userVo.getAvatar());
                    user.setStatus(userVo.getStatus());
                    users.add(user);
                }
            }
            return imService.batchSyncUsersToIm(users);
        } catch (Exception e) {
            log.error("批量同步用户到IM失败: {}", e.getMessage(), e);
            return R.fail("批量同步用户失败: " + e.getMessage());
        }
    }

    @Operation(summary = "发送消息", description = "发送私聊消息")
    @PostMapping("/message/send")
    public R<Map<String, Object>> sendMessage(@RequestBody Map<String, Object> messageData) {
        try {
            Long fromUserId = LoginHelper.getUserId();
            
            // 检查必要参数
            if (!messageData.containsKey("toUserId") || messageData.get("toUserId") == null) {
                return R.fail("接收者ID不能为空");
            }
            if (!messageData.containsKey("content") || messageData.get("content") == null) {
                return R.fail("消息内容不能为空");
            }
            
            Long toUserId = Long.valueOf(messageData.get("toUserId").toString());
            String content = messageData.get("content").toString();
            String messageType = messageData.getOrDefault("messageType", "text").toString();
            
            R<Void> result = imService.sendMessage(fromUserId, toUserId, content, messageType);
            if (result.getCode() == 200) {
                // 返回消息ID，避免前端重复
                Map<String, Object> data = new HashMap<>();
                String messageId = imService.getMessageId(fromUserId, toUserId, content, messageType);
                if (messageId != null) {
                    data.put("messageId", messageId);
                } else {
                    // 如果获取不到消息ID，生成一个临时的
                    data.put("messageId", "temp_" + System.currentTimeMillis());
                }
                return R.ok(data);
            }
            return R.fail(result.getMsg());
        } catch (Exception e) {
            log.error("发送消息失败: {}", e.getMessage(), e);
            return R.fail("发送消息失败: " + e.getMessage());
        }
    }

    @Operation(summary = "发送群组消息", description = "发送群组消息")
    @PostMapping("/message/send-group")
    public R<Void> sendGroupMessage(@RequestBody Map<String, Object> messageData) {
        try {
            Long fromUserId = LoginHelper.getUserId();
            
            // 检查必要参数
            if (!messageData.containsKey("groupId") || messageData.get("groupId") == null) {
                return R.fail("群组ID不能为空");
            }
            if (!messageData.containsKey("content") || messageData.get("content") == null) {
                return R.fail("消息内容不能为空");
            }
            
            String groupId = messageData.get("groupId").toString();
            String content = messageData.get("content").toString();
            String messageType = messageData.getOrDefault("messageType", "text").toString();
            
            return imService.sendGroupMessage(fromUserId, groupId, content, messageType);
        } catch (Exception e) {
            log.error("发送群组消息失败: {}", e.getMessage(), e);
            return R.fail("发送群组消息失败: " + e.getMessage());
        }
    }


    @Operation(summary = "获取用户IM信息", description = "获取用户IM相关信息")
    @GetMapping("/user/info")
    public R<Map<String, Object>> getUserImInfo() {
        try {
            Long userId = LoginHelper.getUserId();
            return imService.getUserImInfo(userId);
        } catch (Exception e) {
            log.error("获取用户IM信息失败: {}", e.getMessage(), e);
            return R.fail("获取用户IM信息失败: " + e.getMessage());
        }
    }



    @Operation(summary = "获取消息历史", description = "获取与指定用户或群组的消息历史")
    @GetMapping("/message/history")
    public R<Map<String, Object>> getMessageHistory(
            @RequestParam String targetId,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "20") Integer pageSize) {
        try {
            Long userId = LoginHelper.getUserId();
            return imService.getMessageHistory(userId, targetId, pageNum, pageSize);
        } catch (Exception e) {
            log.error("获取消息历史失败: {}", e.getMessage(), e);
            return R.fail("获取消息历史失败: " + e.getMessage());
        }
    }

    @Operation(summary = "检查IM表是否存在", description = "检查IM相关表是否存在")
    @GetMapping("/check-tables")
    public R<Map<String, Object>> checkImTables() {
        try {
            Map<String, Object> result = new java.util.HashMap<>();
            
            // 检查im_message表
            try {
                imMessageService.count();
                result.put("im_message", "存在");
            } catch (Exception e) {
                result.put("im_message", "不存在或错误: " + e.getMessage());
            }
            
            // 检查im_group表
            try {
                imGroupService.count();
                result.put("im_group", "存在");
            } catch (Exception e) {
                result.put("im_group", "不存在或错误: " + e.getMessage());
            }
            
            return R.ok(result);
        } catch (Exception e) {
            log.error("检查IM表失败: {}", e.getMessage(), e);
            return R.fail("检查IM表失败: " + e.getMessage());
        }
    }

    @Operation(summary = "检查WebSocket连接状态", description = "检查当前在线的WebSocket用户")
    @GetMapping("/check-websocket")
    public R<Map<String, Object>> checkWebSocketStatus() {
        try {
            Map<String, Object> result = new java.util.HashMap<>();
            
            // 检查Spring WebSocket连接
            try {
                Set<String> springSessions = WebSocketSessionHolder.getSessionsAll();
                result.put("spring_websocket_users", springSessions);
                result.put("spring_websocket_count", springSessions.size());
            } catch (Exception e) {
                result.put("spring_websocket_error", e.getMessage());
            }
            
            return R.ok(result);
        } catch (Exception e) {
            log.error("检查WebSocket状态失败: {}", e.getMessage(), e);
            return R.fail("检查WebSocket状态失败: " + e.getMessage());
        }
    }

    @Operation(summary = "测试IM模块", description = "测试IM模块是否正常启动")
    @GetMapping("/test")
    public R<String> testIm() {
        log.info("=== IM模块测试API被调用 ===");
        log.info("当前时间: {}", System.currentTimeMillis());
        log.info("IM配置状态: enabled={}", imProperties.isEnabled());
        return R.ok("IM模块启动正常，时间: " + System.currentTimeMillis());
    }

    @Operation(summary = "测试创建群聊API", description = "测试创建群聊API是否可访问")
    @GetMapping("/group/test")
    public R<String> testCreateGroup() {
        log.info("=== 创建群聊API测试被调用 ===");
        return R.ok("创建群聊API可访问");
    }

    @Operation(summary = "创建群聊", description = "创建新的群聊")
    @PostMapping("/group/create")
    public R<Map<String, Object>> createGroup(@RequestBody Map<String, Object> groupData) {
        try {
            Long ownerId = LoginHelper.getUserId();
            String groupName = groupData.get("groupName").toString();
            String description = groupData.getOrDefault("description", "").toString();
            String avatar = groupData.getOrDefault("avatar", "").toString();
            // 安全地转换memberIds，支持Integer和Long类型
            List<Long> memberIds = new ArrayList<>();
            Object memberIdsObj = groupData.getOrDefault("memberIds", new ArrayList<>());
            if (memberIdsObj instanceof List) {
                @SuppressWarnings("unchecked")
                List<Object> rawMemberIds = (List<Object>) memberIdsObj;
                for (Object id : rawMemberIds) {
                    if (id instanceof Integer) {
                        memberIds.add(((Integer) id).longValue());
                    } else if (id instanceof Long) {
                        memberIds.add((Long) id);
                    } else if (id instanceof String) {
                        try {
                            memberIds.add(Long.parseLong((String) id));
                        } catch (NumberFormatException e) {
                            log.warn("无法解析成员ID: {}", id);
                        }
                    }
                }
            }
            
            R<Map<String, Object>> result = imService.createGroup(ownerId, groupName, description, avatar, memberIds);
            return result;
        } catch (Exception e) {
            log.error("创建群聊失败: {}", e.getMessage(), e);
            return R.fail("创建群聊失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取群聊列表", description = "获取当前用户参与的群聊列表")
    @GetMapping("/group/list")
    public R<List<Map<String, Object>>> getGroupList() {
        try {
            Long userId = LoginHelper.getUserId();
            R<List<Map<String, Object>>> result = imService.getUserGroups(userId);
            return result;
        } catch (Exception e) {
            log.error("获取群聊列表失败: {}", e.getMessage(), e);
            return R.fail("获取群聊列表失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取会话列表", description = "获取当前用户的聊天会话列表")
    @GetMapping("/conversation/list")
    public R<List<Map<String, Object>>> getConversationList() {
        try {
            Long userId = LoginHelper.getUserId();
            R<List<Map<String, Object>>> result = imService.getConversationList(userId);
            return result;
        } catch (Exception e) {
            log.error("获取会话列表失败: {}", e.getMessage(), e);
            return R.fail("获取会话列表失败: " + e.getMessage());
        }
    }

    @Operation(summary = "标记消息已读", description = "标记私聊或群聊消息为已读")
    @PostMapping("/message/mark-read")
    public R<Void> markMessagesAsRead(@RequestParam(required = false) Long toUserId, 
                                     @RequestParam(required = false) String groupId) {
        try {
            Long userId = LoginHelper.getUserId();
            R<Void> result = imService.markMessagesAsRead(userId, toUserId, groupId);
            return result;
        } catch (Exception e) {
            log.error("标记消息已读失败: {}", e.getMessage(), e);
            return R.fail("标记消息已读失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取群聊详情", description = "获取群聊详细信息")
    @GetMapping("/group/{groupId}")
    public R<Map<String, Object>> getGroupInfo(@PathVariable String groupId) {
        try {
            R<Map<String, Object>> result = imService.getGroupInfo(groupId);
            return result;
        } catch (Exception e) {
            log.error("获取群聊详情失败: {}", e.getMessage(), e);
            return R.fail("获取群聊详情失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取群成员列表", description = "获取群聊成员列表")
    @GetMapping("/group/{groupId}/members")
    public R<List<Map<String, Object>>> getGroupMembers(@PathVariable String groupId) {
        try {
            R<List<Map<String, Object>>> result = imService.getGroupMembers(groupId);
            return result;
        } catch (Exception e) {
            log.error("获取群成员列表失败: {}", e.getMessage(), e);
            return R.fail("获取群成员列表失败: " + e.getMessage());
        }
    }

    @Operation(summary = "添加群成员", description = "向群聊中添加新成员")
    @PostMapping("/group/{groupId}/members")
    public R<Void> addGroupMembers(@PathVariable String groupId, @RequestBody Map<String, Object> memberData) {
        try {
            Long operatorId = LoginHelper.getUserId();
            @SuppressWarnings("unchecked")
            List<Object> memberIdsObj = (List<Object>) memberData.get("memberIds");
            
            // 安全地转换为Long类型，支持大整数
            List<Long> memberIds = new ArrayList<>();
            if (memberIdsObj != null) {
                for (Object memberId : memberIdsObj) {
                    if (memberId != null) {
                        try {
                            String idStr = memberId.toString();
                            // 使用BigInteger处理大整数，然后转换为Long
                            if (idStr.length() > 15) {
                                // 对于超长整数，使用BigInteger
                                java.math.BigInteger bigInt = new java.math.BigInteger(idStr);
                                if (bigInt.compareTo(java.math.BigInteger.valueOf(Long.MAX_VALUE)) <= 0) {
                                    memberIds.add(bigInt.longValue());
                                } else {
                                    log.warn("用户ID超出Long范围: {}", memberId);
                                }
                            } else {
                                // 普通整数直接转换
                                Long id = Long.valueOf(idStr);
                                memberIds.add(id);
                            }
                        } catch (NumberFormatException e) {
                            log.warn("无效的用户ID: {}", memberId);
                        }
                    }
                }
            }
            
            if (memberIds.isEmpty()) {
                return R.fail("没有有效的用户ID");
            }
            
            R<Void> result = imService.addGroupMembers(groupId, operatorId, memberIds);
            return result;
        } catch (Exception e) {
            log.error("添加群成员失败: {}", e.getMessage(), e);
            return R.fail("添加群成员失败: " + e.getMessage());
        }
    }

    @Operation(summary = "移除群成员", description = "从群聊中移除成员")
    @DeleteMapping("/group/{groupId}/members/{userId}")
    public R<Void> removeGroupMember(@PathVariable String groupId, @PathVariable Long userId) {
        try {
            Long operatorId = LoginHelper.getUserId();
            R<Void> result = imService.removeGroupMember(groupId, operatorId, userId);
            return result;
        } catch (Exception e) {
            log.error("移除群成员失败: {}", e.getMessage(), e);
            return R.fail("移除群成员失败: " + e.getMessage());
        }
    }

    @Operation(summary = "更新群信息", description = "更新群聊基本信息")
    @PutMapping("/group/{groupId}")
    public R<Void> updateGroupInfo(@PathVariable String groupId, @RequestBody Map<String, Object> groupData) {
        try {
            Long operatorId = LoginHelper.getUserId();
            String groupName = groupData.getOrDefault("groupName", "").toString();
            String description = groupData.getOrDefault("description", "").toString();
            String avatar = groupData.getOrDefault("avatar", "").toString();
            
            R<Void> result = imService.updateGroupInfo(groupId, operatorId, groupName, description, avatar);
            return result;
        } catch (Exception e) {
            log.error("更新群信息失败: {}", e.getMessage(), e);
            return R.fail("更新群信息失败: " + e.getMessage());
        }
    }

    @Operation(summary = "退出群聊", description = "退出群聊")
    @PostMapping("/group/{groupId}/quit")
    public R<Void> quitGroup(@PathVariable String groupId) {
        try {
            Long userId = LoginHelper.getUserId();
            R<Void> result = imService.quitGroup(groupId, userId);
            return result;
        } catch (Exception e) {
            log.error("退出群聊失败: {}", e.getMessage(), e);
            return R.fail("退出群聊失败: " + e.getMessage());
        }
    }

    @Operation(summary = "解散群聊", description = "解散群聊（仅群主）")
    @PostMapping("/group/{groupId}/disband")
    public R<Void> disbandGroup(@PathVariable String groupId) {
        try {
            Long operatorId = LoginHelper.getUserId();
            R<Void> result = imService.disbandGroup(groupId, operatorId);
            return result;
        } catch (Exception e) {
            log.error("解散群聊失败: {}", e.getMessage(), e);
            return R.fail("解散群聊失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取IM用户列表", description = "获取所有用户列表用于IM联系人，无需权限验证")
    @GetMapping("/user/list")
    public R<List<Map<String, Object>>> getImUserList() {
        try {
            // 直接调用系统用户服务，不进行权限检查
            List<SysUserVo> users = userService.selectUserList(new com.nbcio.system.domain.bo.SysUserBo());
            
            log.info("从数据库查询到用户数量: {}", users.size());
            for (SysUserVo user : users) {
                log.info("用户: {} ({}), imStatus: {}", user.getUserName(), user.getNickName(), user.getImStatus());
            }
            
            List<Map<String, Object>> userList = users.stream()
                    .filter(user -> "0".equals(user.getStatus())) // 只返回启用的用户
                    .map(user -> {
                        Map<String, Object> userMap = new java.util.HashMap<>();
                        userMap.put("userId", user.getUserId());
                        userMap.put("userName", user.getUserName());
                        userMap.put("nickName", user.getNickName());
                        userMap.put("avatar", user.getAvatar());
                        userMap.put("email", user.getEmail());
                        userMap.put("phonenumber", user.getPhonenumber());
                        userMap.put("status", user.getStatus());
                        userMap.put("imStatus", user.getImStatus() != null ? user.getImStatus() : "offline");
                        userMap.put("imLastOnlineTime", user.getImLastOnlineTime());
                        return userMap;
                    })
                    .collect(java.util.stream.Collectors.toList());
            
            log.info("返回给前端的用户列表数量: {}", userList.size());
            return R.ok(userList);
        } catch (Exception e) {
            log.error("获取IM用户列表失败: {}", e.getMessage(), e);
            return R.fail("获取用户列表失败: " + e.getMessage());
        }
    }
}
